好的開始,是成功的一半。
不管是前端、後端,當一個團隊每個成員撰寫程式的風格不同,對於維護、開發都相對會困難些。如果有個統一的規定,會一定程度提高專案開發效率。這類型的 tools 在每個程式都有相對應的 linter 可以使用。
這次開頭第一篇就從名字很淺顯易懂的 rails_best_practices
開始吧!一看就知道這個 gem 在做什麼(雖然說 官方網站 已經有點久沒更新 & Github Commit 沒什麼新的東西,但至少還是一個不錯使用的工具,也在上個專案使用了約一年多左右)
# Gemfile
gem "rails_best_practices"
# At the root directory of a Rails app
bundle exec rails_best_practices
# for HTML output
bundle exec rails_best_practices -f html
# Schema
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "content"
t.boolean "is_available"
t.integer "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "tel"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
# model
# user.rb
class User < ApplicationRecord
has_many :posts
end
# post.rb
class Post < ApplicationRecord
belongs_to :user
end
在 post index 頁面中,假如想顯示 Post 所有欄位 & 來自於哪個 User Name,可能會這樣子寫:
# app/views/posts/index.html.erb
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= post.is_available %></td>
# User Name
<td><%= post.user.name %></td>
</tr>
<% end %>
執行 bundle exec rails_best_practices
會發現出現 law of demeter
的錯誤訊息,原因其實就是出在 post.user.name
的部分
/blog/app/views/posts/index.html.erb:22 - law of demeter
Please go to https://rails-bestpractices.com to see more useful Rails Best Practices.
Found 1 warnings.
可以寫個 user_name
方法來呼叫關聯 user 的 name,不過如果要顯示 user 更多的其他欄位(e.g. email
),等於要一直寫更多的方法,這時候其實可以用 delegate 來做,相對於行數也比較短。
# model
# user.rb
class User < ApplicationRecord
has_many :posts
end
# post.rb
class Post < ApplicationRecord
belongs_to :user
# (1)
def user_name
user.name
end
def user_email
user.email
end
# (2)
delegate :name, :email, to: :user, prefix: true
end
# app/views/posts/index.html.erb
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= post.is_available %></td>
# User Name & Email
<td><%= post.user_name %></td>
<td><%= post.user_email %></td>
</tr>
<% end %>
透過 Delegate 來把 attributes 給關聯的 model 來使用讓邏輯更容易理解,更改後再跑一次就 No warning found,沒問題啦!
Source Code: |=============================================================================================================================|
Please go to https://rails-bestpractices.com to see more useful Rails Best Practices.
No warning found. Cool!